#pragma once;
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string>
#include <stack>
#include <vector>
#include <boost/shared_array.hpp>

#include "baseutil.h"
#include "UnicodeConvert.h"

using namespace std;
namespace yet{
//diff from SharedArray , by c-style string reason
template<typename T>
class BaseString: public WithTag {
	static const int STACK_SIZE = 16;
private:
	T stackBuff[STACK_SIZE];
	boost::shared_array<T> autoArray;
	T* pt;
	int capcity;
	int count;

public:
	virtual ~BaseString();
	BaseString();
	BaseString(int capcity_);
	BaseString(const T* s);
	BaseString(const T* s, int len);
	BaseString(T ch, int repeatCount);
	BaseString(const BaseString<T>& other);
public:
	BaseString<T>& operator=(const BaseString<T>& other);
	void assign(const BaseString<T>& other);
	void init(int capcity_);
	void copyFrom(const T* array, int len);
	//will delete[] s, when ShareVector Objects destructor
	void manage(T* array, int len, int capcity_);
	void clear();
public:
	T* buffer() ;
	const T* buffer() const;
	T* bufferW();
	const T* bufferR() const;
	void ensureCapcity(int cap_);
	int getCapcity();
	void setLength(int len);
	int length() const;
	int size() const;
	bool empty() const;
	const T* cString();
	BaseString<T> clone() const;
//	basic_string<T> stdString();
public:
	T first() const;
	T& first();
	T last() const;
	T& last();
	T get(int index) const;
	T& getRef(int index);
	T operator[](int index) const;
	T& operator[](int index);
	void set(int index, T val);
public:
	void fill(int from, T val);
	void fill(int from, int len, T val);
	void replace(int delFrom, int delLength, const T* insertString, int insertLength);
	void replace(int from, int length, const BaseString<T>& s);
	void replace(int from, int length, const T* s);
	void insert(int index, T val);
	void insert(int index, const T* s, int len);
	void insert(int index, const BaseString<T>& s);
	void remove(int index);
	void remove(int index, int size);
	void append(T val);
	void append(const T* s, int len);
	void append(const BaseString<T>& s);
	//[from, from+len) eq [other, other+len);
	bool rangeEquals(int from, const T* other, int len) const;
	bool endWith(const T* other) const;
	bool endWith(const BaseString<T>& other) const;
	bool endWith(const T* other, int len) const;
	bool startWith(const BaseString<T>& other) const;
	bool startWith(const T* other, int len) const;
	bool startWith(const T* other) const;
	bool equals(const T* other, int len) const;
	bool equals(const T* other) const;
	bool equals(const BaseString<T>& other) const;
	BaseString<T> subString(int from, int length) const;
	BaseString<T> subString(int from) const;
protected:
	//keep 1 for c-string 0.
	void preWrite(int increase = 0);
	int getMinCapcity();
	int getGrowSize(int need);
private:
	int strLength(const T* s) const;
private:
	int unique() const;
	void setPtr(T* p);
};


typedef BaseString<char> String;
typedef BaseString<wchar_t> WString;


template<typename T>
BaseString<T>::~BaseString() {

}
template<typename T>
inline BaseString<T>::BaseString() :
		capcity(STACK_SIZE),
		count(0),
		pt(stackBuff) {
}
template<typename T>
inline BaseString<T>::BaseString(int capcity_) :
		capcity(STACK_SIZE),
		count(0),
		pt(stackBuff) {
	init(capcity_);
}
template<typename T>
inline BaseString<T>::BaseString(const T* s) :
		capcity(STACK_SIZE),
		count(0),
		pt(stackBuff) {
	if (s) {
		copyFrom(s, strLength(s));
	}
}
template<typename T>
inline BaseString<T>::BaseString(const BaseString<T>& other) :
		capcity(STACK_SIZE),
		count(0),
		pt(stackBuff) {
	assign(other);
}
template<typename T>
inline BaseString<T>::BaseString(const T* s, int len) :
		capcity(STACK_SIZE),
		count(0),
		pt(stackBuff) {
	assert(len >=0);
	if (s && len) {
		copyFrom(s, len);
	}
}

template<typename T>
BaseString<T>::BaseString(T ch, int repeatCount) :
		capcity(STACK_SIZE),
		count(0),
		pt(stackBuff) {
	if (repeatCount) {
		init(repeatCount);
		setLength(repeatCount);
		fill(0, ch);
	}
}
template<typename T>
inline BaseString<T>& BaseString<T>::operator=(const BaseString<T>& other) {
	assign(other);
	return *this;
}
template<typename T>
void BaseString<T>::assign(const BaseString<T>& other) {
	if (this != &other) {
		count = other.count;
		capcity = other.capcity;
		if (other.pt == other.stackBuff) {
			pt = stackBuff;
			for (int i = 0; i < count; ++i) {
				pt[i] = other.pt[i];
			}
		} else {
			autoArray = other.autoArray;
			pt = autoArray.get();
		}
	}
}

template<typename T>
inline void BaseString<T>::clear() {
	count = 0;
	autoArray.reset();
	pt = stackBuff;
	capcity = STACK_SIZE;
}
template<typename T>
void BaseString<T>::init(int capcity_) {
	assert(capcity_ >=0);
	count = 0;
	if ((capcity_ >= capcity) || !unique()) {
		capcity = capcity_ + 1;
		T* buf = new T[capcity];
		setPtr(buf);
	}else{//unique && capcity_ == capcity
		//do nothing
	}
}
template<typename T>
void BaseString<T>::copyFrom(const T* array, int len) {
	assert(len>=0);
	count = len;
	if (len < capcity && unique()) {
		ArrayMove(pt, array, len); //len * 1
		return;
	}
	//len >= cap() or !unique()
	capcity = len + 1;
	T* buf = new T[capcity];
	setPtr(buf);
	ArrayMove(pt, array, len); //len * 1
}
//will delete[] s, when ShareVector Objects destructor
template<typename T>
void BaseString<T>::manage(T* array, int len, int capcity_) {
	assert(array);
	assert(len>=0);
	assert(capcity_ >= len);

	if (capcity_ == len) {
		slog << error << "manage string lenth == capcity_" << endln;
		copyFrom(array, len);
		delete[] array;
	} else { //capcity > len
		setPtr(array);
		count = len;
		capcity = capcity_;
	}
}
template<typename T>
inline const T* BaseString<T>::buffer() const {
	return pt;
}
template<typename T>
inline T* BaseString<T>::buffer() {
	preWrite();
	return pt;
}
template<typename T>
inline const T* BaseString<T>::bufferR() const {
	return pt;
}
template<typename T>
inline T* BaseString<T>::bufferW() {
	preWrite();
	return pt;
}
template<typename T>
inline void BaseString<T>::ensureCapcity(int cap_) {
	if (cap_ > getCapcity()) {
		preWrite(Max(0, cap_ - count));
	}
}
template<typename T>
inline int BaseString<T>::getCapcity() {
	return Max(0, capcity -1);
}

template<typename T>
inline void BaseString<T>::setLength(int len) {
	assert(len>=0);
	assert( len < capcity);
	count = len;
}
template<typename T>
inline int BaseString<T>::length() const {
	return count;
}
template<typename T>
inline int BaseString<T>::size() const {
	return count;
}
template<typename T>
inline bool BaseString<T>::empty() const {
	return !count;
}
template<typename T>
inline const T* BaseString<T>::cString() {
	pt[count] = 0;
	return pt;
}
template<typename T>
inline BaseString<T> BaseString<T>::clone() const {
	BaseString<T> s(buffer(), length());
	return s;
}
template<typename T>
inline T BaseString<T>::first() const {
	assert(!empty());
	return pt[0];
}
template<typename T>
inline T& BaseString<T>::first() {
	assert(!empty());
	return pt[0];
}
template<typename T>
inline T BaseString<T>::last() const {
	assert(!empty());
	return pt[count - 1];
}
template<typename T>
inline T& BaseString<T>::last() {
	assert(!empty());
	return pt[count - 1];
}
template<typename T>
inline T BaseString<T>::get(int index) const {
	assert(index>=0);
	assert( index < count);
	return pt[index];
}
template<typename T>
inline T BaseString<T>::operator[](int index) const {
	assert(index >=0);
	return pt[index];
}
template<typename T>
inline T& BaseString<T>::operator[](int index) {
	assert( index >= 0);
	return pt[index];
}
template<typename T>
T& BaseString<T>::getRef(int index) {
	assert(index>=0);
	assert( index <= count);
	if (index == count) {
		append(T());
	} else {
		preWrite();
	}
	return pt[index];
}
template<typename T>
void BaseString<T>::set(int index, T val) {
	assert(index>=0);
	assert( index <= count);
	if (index == count) {
		append(val);
	} else {
		preWrite();
		pt[index] = val;
	}
}
template<typename T>
void BaseString<T>::fill(int from, T val) {
	assert(from>=0);
	assert(from < count);
	preWrite();
	RangeSet(pt, count - from, val);
}
template<typename T>
void BaseString<T>::fill(int from, int len, T val) {
	assert(from>=0);
	assert(len>=0);
	assert(from + len <= count);
	if (len) {
		preWrite();
		RangeSet(pt, from, len, val);
	}
}
template<typename T>
void BaseString<T>::replace(int delFrom, int delLength, const T* insertString, int insertLength) {
	assert(delFrom>=0);
	assert(delLength>=0);
	assert(insertLength>=0);
	if (!delLength && !insertLength) { //modify nothing
		return;
	}
	assert(delFrom + delLength <= count);
	if (insertString == 0) {
		assert(insertLength == 0);
	}

	int newCount = count - delLength + insertLength;

	if (unique() && newCount < capcity) {
		ArrayMove(pt + delFrom + insertLength, pt + delFrom + delLength, count - delFrom - delLength);
		ArrayMove(pt + delFrom, insertString, insertLength);
		count = newCount;
		return;
	}

	int newCap = getGrowSize(newCount);
	T* array = new T[newCap];
	ArrayMove(array, pt, delFrom);
	ArrayMove(array + delFrom, insertString, insertLength);
	ArrayMove(array + delFrom + insertLength, pt + delFrom + delLength, count - delFrom - delLength);

	setPtr(array);
	capcity = newCap;
	count = newCount;

}
template<typename T>
inline void BaseString<T>::replace(int from, int length, const BaseString<T>& s) {
		replace(from, length, s.buffer(), s.length());
}
template<typename T>
inline void BaseString<T>::replace(int from, int length, const T* s) {
	int len = strLength(s);
	replace(from, length, s, len);
}
template<typename T>
inline void BaseString<T>::insert(int index, T val) {
	replace(index, 0, &val, 1);
}
template<typename T>
inline void BaseString<T>::insert(int index, const T* s, int len) {
	replace(index, 0, s, len);
}
template<typename T>
inline void BaseString<T>::insert(int index, const BaseString<T>& s) {
	replace(index, 0, s.buffer(), s.length());
}
template<typename T>
inline void BaseString<T>::remove(int index) {
	assert(index>=0);
	replace(index, 1, 0, 0);
}
template<typename T>
inline void BaseString<T>::remove(int index, int size) {
	assert(index>=0);
	assert(size>=0);
	replace(index, size, 0, 0);
}
template<typename T>
inline void BaseString<T>::append(T val) {
	replace(count, 0, &val, 1);
}
template<typename T>
inline void BaseString<T>::append(const T* s, int len) {
	replace(count, 0, s, len);
}
template<typename T>
inline void BaseString<T>::append(const BaseString<T>& s) {
	replace(count, 0, s.buffer(), s.length());
}

//[from, from+len) eq [other, other+len);
template<typename T>
bool BaseString<T>::rangeEquals(int from, const T* other, int len) const {
	assert(len>=0);
	assert(from>=0);
	if (from + len <= length()) {
		if (len) {
			if (other) {
				const T* buf = pt + from;
				for (int i = 0; i < len; ++i) {
					if (!(buf[i] == other[i])) {
						return false;
					}
				}
				return true;
			} else {
				if (from == length()) {
					return true;
				}
			}
		} else {
			return true;
		}
	}
	return false;
}
template<typename T>
inline bool BaseString<T>::endWith(const T* other) const {
	return endWith(other, other ? strLength(other) : 0);
}
template<typename T>
inline bool BaseString<T>::endWith(const BaseString<T>& other) const {
	return endWith(other.buffer(), other.length());
}
template<typename T>
inline bool BaseString<T>::endWith(const T* other, int len) const {
	if (length() >= len) {
		return rangeEquals(length() - len, other, len);
	}
	return false;
}
template<typename T>
inline bool BaseString<T>::startWith(const BaseString<T>& other) const {
	return rangeEquals(0, other.buffer(), other.length());
}
template<typename T>
inline bool BaseString<T>::startWith(const T* other, int len) const {
	return rangeEquals(0, other, len);
}
template<typename T>
bool BaseString<T>::startWith(const T* other) const {
	if (other == 0) {
		return true;
	} else {
		const T* buf = buffer();
		int c = 0;
		while (c < count && other[c]) {
			if (buf[c] != other[c]) {
				return false;
			}
			++c;
		}
		return c <= count && other[c] == 0;
	}
}
template<typename T>
inline bool BaseString<T>::equals(const T* other, int len) const {
	assert(len>=0);
	if (length() == len) {
		return rangeEquals(0, other, len);
	}
	return false;
}
template<typename T>
bool BaseString<T>::equals(const T* other) const {
	if (other == 0) {
		return count == 0;
	} else {
		const T* buf = buffer();
		int c = 0;
		while (c < count && other[c]) {
			if (buf[c] != other[c]) {
				return false;
			}
			++c;
		}
		return c == count && other[c] == 0;
	}
}
template<typename T>
bool BaseString<T>::equals(const BaseString<T>& other) const {
	if(this == &other){
		return true;
	}
	if (other.buffer() == buffer()) {
		return other.count == count;
	}
	return equals(other.buffer(), other.count);
}
template<typename T>
BaseString<T> BaseString<T>::subString(int from, int length) const {
	assert(from >=0);
	assert(length>=0);
	assert(from + length <= count);
	return BaseString<T>(buffer() + from, length);
}
template<typename T>
BaseString<T> BaseString<T>::subString(int from) const {
	assert(from >=0);
	assert(from < count);
	int length = count - from;
	return BaseString<T>(buffer() + from, length);
}
//keep 1 for c-string 0.
template<typename T>
void BaseString<T>::preWrite(int increase = 0) {
	assert(increase >=0);
	int newCount = count + increase;
	if (unique() && newCount < capcity) {
		return;
	}

	capcity = getGrowSize(count + increase);
	T* buf = new T[capcity];
	if (count) {
		ArrayMove(buf, pt, count); //count * 1
	}
	setPtr(buf);
}
template<typename T>
inline int BaseString<T>::getMinCapcity() {
	return STACK_SIZE;
}
template<typename T>
inline int BaseString<T>::getGrowSize(int need) {
	assert(need >=0);
	return Max(getMinCapcity(), need *2);
}
template<typename T>
inline int BaseString<T>::strLength(const T* s) const {
	int len = 0;
	if (s) {
		while (s[len]) {
			++len;
		}
	}
	return len;
}
template<typename T>
inline int BaseString<T>::unique() const {
	return autoArray.unique(); // ==!arr || arr.unique();
}
template<typename T>
inline void BaseString<T>::setPtr(T* p) {
	pt = p;
	autoArray.reset(p);
}

inline ostream& operator <<(ostream& slog, const String& s) {
	slog << (string(s.buffer(), s.length()));
	return slog;
}


}
